package cn.yazy.异常;
/**
 * 异常:在程序中运行过程中出现的错误,异常就是程序运行过程中出现了不正常的现象导致程序的中断.
 * 在Java中,把各种异常现象进行了抽象形成了异常类.
 *
 * 异常主要分为:Error错误,一般性异常,运行时异常
 *
 * 错误:如果应用程序中出现了Error,那么将无法恢复,只能重新启动应用程序,最典型的Error异常
 * 是:OutOfMemoryError  内存溢出
 *
 * 一般性异常(编译时异常):
 * 这种异常必须显示的处理,不显示处理Java程序异常,编译将无法通过.编译器强制普通异常必须try...catch处理,
 * 或用throws声明继续抛给上层调用方法处理,所以普通异常有称为check异常.
 *
 * 运行时异常(RuntimeException):
 * 这种系统异常可以处理,也不是不处理,所以编译器不强制用try...catch处理或throws声明抛出.如果出现了运行时异常
 * 一般都是程序员自己的问题,健壮的程序一般不会出现这种异常
 *
 * 异常的处理:
 * 运行时异常不需要预处理,通过规范代码可以避免产生这种异常.
 * 编译时异常必须要预处理,否则会编译错误,有俩种预处理方式:
 * 1.捕获处理
 * 2.抛出处理
 *
 * 异常的捕获处理:
 * 1.try/catch/finally
 * 异常的捕获和处理需要采用try和catch来处理具体格式如下:
 * try{
 *
 * }catch(){
 *
 * }catch(){//catch可以有一个或多个
 *
 * }finally{
 *
 * }
 * try中包含了可以产生的异常代码,try后面的catch,catch可以有一个或多个,当出现多个catch时,要注意异常
 * 的顺序,小异常在前,大异常在后.catch中是需要捕获的异常
 * 当try中出现异常时,出现异常下面的代码不会执行,会马上跳转到相应的catch中,如果没有异常则不会跳转到catch中
 * finally代码块是不管是否出现异常,finally里面的代码都会在执行,finally和catch可以分开使用,但finally
 * 必须与try一起使用
 * 例如:
 * try{
 *
 * }catch(){
 *
 * }
 *
 * try{
 *
 * }finally{
 *
 * }
 *
 *@author ZhangAJ:
 *@version 创建时间：2022年9月29日上午8:38:12
 */
public class ExceptionDemo {

    public static void main(String[] args) {
        //面试题:请阐述final/finally/finalize的区别
		/*
		 * 三者的区别
		1.性质不同
			final为关键字;
		    finalize()为方法;
			finally为为区块标志,用于try语句中;
		2. 作用
			final为用于标识常量的关键字,final标识的关键字存储在常量池中(在这里final常量的具体用法将在
			下面进行介绍);
			finalize()方法在Object中进行了定义,用于在对象“消失”时,由JVM进行调用用于对对象 进行垃圾回收,
			类似于C++中的析构函数;用户自定义时,用于释放对象占用的资源(比如进行 I/0操作);
			finally{}用于标识代码块,与try{ }进行配合,不论try中的代码执行完或没有执行完(这里指有异常),
			该代码块之中的程序必定会进行 .

			一.final的用法
			被final修饰的类不可以被继承
			被final修饰的方法不可以被重写
			被final修饰的变量不可以被改变,如果修饰引用,那么表示引用不可变,引用指向的内容可变.
			被final修饰的方法,JVM会尝试将其内联,以提高运行效率
			被final修饰的常量,在编译阶段会存入常量池中
			除此之外,编译器对final域要遵守的两个重排序规则更好:
			在构造函数内对一个final域的写入,与随后把这个被构造对象的引用赋值给一个引用变量,
			这两个操作之间不能重排序,初次读一个包含final域的对象的引用,与随后初次读这个final域,
			这两个操作之间不能重排序

			二.finally的用法
			finally是在异常处理中的使用的
			不管 try 语句块正常结束还是异常结束,finally 语句块是保证要执行的.
			如果 try 语句块正常结束,那么在 try 语句块中的语句都执行完之后,再执行 finally 语句块.
			不管有没有出现异常,finally块中的代码都会执行;
			当try和catch中有return时,finally仍然会执行;
			finally是在return后面的表达式运算后执行的(此时并没有返回运算后的值,而是先把要返回的值保
			存起来,无论finally中的代码怎么样,返回的值都不会改变,仍然是之前保存的值),所以函数返回值是
			在finally执行前确定好的;
			finally中最好不要包含return,否则程序会提前退出,返回值不是try或catch中保存的返回值.

			三.finalize的用法
			finalize()是Java中Object的一个protected方法.返回值为空,当该对象被垃圾回收器回收时,
			会调用该方法.
			关于finalize()函数
			finalize不等价于c++中的析构函数;
			对象可能不被垃圾机回收器回收;
			垃圾回收不等于析构;
			垃圾回收只与内存有关;
			垃圾回收和finalize()都是靠不住的,只要JVM还没有快到耗尽内存的地步,它是不会浪费时间进行
			垃圾回收的;
			程序强制终结后,那些失去引用的对象将会被垃圾回收.(System.gc())
         *
		 */

        //try - catch异常捕获1
        try{
            //1.对可能出现异常的代码进行检测
            //2.如果try代码块中某条语句出现异常就立即跳转到对应的catch中,try后边的代码不再执行
            //3.当try块中出现了多个检测异常需要处理,可以通过多个catch子句分别进行处理

        }catch(NullPointerException e1){
            //NullPointerException 空指针异常
            //如果出现异常类型1
            //则该代码块处理,在开发阶段,一般异常处理,要么打印错误信息(e1.printStackTrace();)
            //要么输出运行日志,保存日志文件(logger.error)
        }catch(ArithmeticException e2){

        }catch(RuntimeException e3){
            //如果捕获异常类型3与捕获异常类型1和2有继承关系,要先捕获子异常,后捕获父异常
            //如果没有继承关系,然后按顺序执行
        }finally{
            //不管是否发生异常,该子句继续执行,一般在该子句中常常用于释放系统资源
        }

        int i1 = 100;
        int i2 = 0;
        try{
            System.out.println("执行1");
            int i3 = i1/i2;
            System.out.println("继续执行2");
        }catch(RuntimeException e){//ArithmeticException (子类)精确处理类
            System.out.println("除数不能为0");
            e.printStackTrace();
        }finally{
            System.out.println("继续执行3");
        }


        int i3 = i1/i2;

    }

}
